package tech.yunland.shop.domain.service;

import com.moyuer.bsf.common.codec.SecureCoder;
import com.moyuer.bsf.domain.dao.OrganDao;
import com.moyuer.bsf.domain.dao.UserDao;
import com.moyuer.bsf.domain.model.User;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import tech.yunland.shop.domain.dao.SchedulerJobDao;
import tech.yunland.shop.domain.model.SchedulerJob;
import tech.yunland.shop.domain.task.LoadJob;

import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 任务调度服务类
 *
 * @author 文卡<wkwenka@gmail.com>  on 17-3-9.
 */
@Service
public class SchedulerJobService {

    @Autowired
    private SchedulerJobDao schedulerJobDao;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private LoadJob loadJob;

    @Autowired
    private UserDao userDao;

    @Autowired
    private OrganDao organDao;

    @Value("${probation_days}")
    private String probationDays;


    /**
     * 获取任务集
     *
     * @return
     */
    public List<SchedulerJob> getSchedulerJobList() {

        String hql = "FROM SchedulerJob WHERE state = 1";
        List<SchedulerJob> schedulerJobs = schedulerJobDao.find(hql);
        return schedulerJobs;
    }

    /**
     * 创建新的定时任务
     *
     * @param schedulerJob
     */
    public void createSchedulerJob(SchedulerJob schedulerJob) throws Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        schedulerJob.setCronExpression(formateDateToCron(schedulerJob.getEndTime()));

        loadJob.runTask(schedulerJob, scheduler);
        schedulerJob.setGroup(schedulerJob.getId());
        schedulerJob.setName(schedulerJob.getId());
        schedulerJobDao.save(schedulerJob);
    }

    /**
     * 更新定时任务
     *
     * @param user
     * @param days
     * @throws Exception
     */
    public void updateSchedulerJob(User user ,Integer days) throws Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        user = getUser(user);

        SchedulerJob schedulerJobByUser = getSchedulerJobByUser(user);

        if (schedulerJobByUser != null) {
            Date endTime = schedulerJobByUser.getEndTime();

            Calendar instance = Calendar.getInstance();
            if (schedulerJobByUser.getState().intValue() == 1){
                instance.setTime(endTime);
            }
            instance.add(Calendar.DATE,days);

            schedulerJobByUser.setEndTime(instance.getTime());
            schedulerJobByUser.setCronExpression(formateDateToCron(instance.getTime()));
            schedulerJobByUser.setState(Integer.valueOf(1));

//            loadJob.rescheduleJob(scheduler, schedulerJobByUser);
            loadJob.runTask(schedulerJobByUser,scheduler);
            schedulerJobDao.saveOrUpdate(schedulerJobByUser);

            if (user.getState().intValue() == 0){
                user.setState(Integer.valueOf(1));
                userDao.saveOrUpdate(user);
            }

        } else {
            throw new RuntimeException("数据异常");
        }


    }


    /**
     * 内部方法 格式化时间
     *
     * @param date
     * @return
     */
    private String formateDateToCron(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
        String dateStr = "";
        if (date != null) {
            dateStr = format.format(date);
        }
        return dateStr;
    }

    private SchedulerJob getSchedulerJobByUser(User user) {
        String hql = "FROM SchedulerJob WHERE 1=1";
        if (user != null) {
            String creator_id = user.getId();
            hql += " AND creator.id=?";

            List<SchedulerJob> schedulerJobs = schedulerJobDao.find(hql, creator_id);

            if (schedulerJobs != null && schedulerJobs.size() > 0) {
                return schedulerJobs.get(0);
            }
        }
        return null;
    }

    private User getUser(User user){
        String account = StringUtils.trimToNull(user.getAccount());
        String password = StringUtils.trimToNull(user.getPassword());
        String securePwd = null;

        try {
            securePwd = SecureCoder.sha1(password);
        } catch (NoSuchAlgorithmException var10) {
            throw new RuntimeException("密码无法解析");
        }

        DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
        criteria.add(Restrictions.eq("account", account));
        criteria.add(Restrictions.eq("password", securePwd));
        criteria.add(Restrictions.ge("state", Integer.valueOf(0)));
        List list = this.userDao.findByCriteria(criteria);
        if (list != null && list.size() > 0){
            if (list.size() == 1){
                return (User)list.get(0);
            }else {
                throw new RuntimeException("用户数据异常");
            }
        }else {
            throw new RuntimeException("用户名或密码错误");
        }

    }

    /**
     * 获取用户有效期天数
     *
     * @param userId
     * @return
     */
    public String updateOrGetValidPeriod(String userId){

        String sql = "SELECT end_time FROM scheduler_job WHERE creator_id=? AND state=1";

        List<Map<String, Object>> bySQL = this.schedulerJobDao.findBySQL(sql, userId);

        if (bySQL != null && bySQL.size() > 0){
            if (bySQL.size() > 1){
                throw new RuntimeException("数据异常");
            }
            Map<String, Object> map = bySQL.get(0);
            Date endTime = (Date) map.get("end_time");
            long intervalMilli = endTime.getTime() - new Date().getTime();

            int i = (int) (intervalMilli / (24 * 60 * 60 * 1000));

            return "" + i;
        }else {

            User user = this.userDao.get(userId);
            SchedulerJob schedulerJob = new SchedulerJob();
            Calendar instance = Calendar.getInstance();
            instance.add(Calendar.DATE,Integer.valueOf(probationDays).intValue());
            schedulerJob.setEndTime(instance.getTime());
            schedulerJob.setOrgan(this.organDao.get(user.getPrimaryOrganId()));
            schedulerJob.setCreator(user);
            schedulerJob.setState(Integer.valueOf(1));
            try {
               this.createSchedulerJob(schedulerJob);
            }catch (Exception e){
                throw new RuntimeException(e.getMessage());
            }
            return Integer.valueOf(probationDays)-1  +"";
        }

    }

}
